﻿using JetBrains.Annotations;

namespace Rsdn.Janus
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using BLToolkit.Data;
    using BLToolkit.Data.Linq;
    using TreeGrid;

    /// <summary>
    ///   Коллекция новых сообщений.
    /// </summary>
    public class NewMessageCollection
        : IOutboxMessageCollection, 
          ITreeNode, 
          IGetData, 
          IOutboxCollection, 
          IKeyedNode, 
          IEnumerable<NewMessage>
    {
        private readonly object _loadFlag = new object();
        private readonly OutboxManagerBase _manager;
        private readonly bool _draftMessage;
        private readonly IServiceProvider _provider;
        private List<NewMessage> _messages;

        internal NewMessageCollection(IServiceProvider provider, OutboxManagerBase manager, bool draftMessage)
        {
            _provider = provider;
            _manager = manager;
            _draftMessage = draftMessage;
        }

        #region IEnumerable<NewMessage> Members

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns></returns>
        [NotNull]
        IEnumerator<NewMessage> IEnumerable<NewMessage>.GetEnumerator()
        {
            CheckLoad();
            return _messages.GetEnumerator();
        }

        #endregion

        #region IGetData Members

        public void GetData(NodeInfo nodeInfo, CellInfo[] cellData)
        {
            cellData[OutboxManagerBase.ForumColumn].Text = Name;
            cellData[OutboxManagerBase.ForumColumn].ImageIndex =
                OutboxImageManager.MsgFolderImageIndex;
        }

        #endregion

        #region IKeyedNode Members

        public string Key
        {
            get { return GetType().Name; }
        }

        #endregion

        #region IOutboxCollection Members

        public string Name
        {
            get { return SR.Outbox.NewMessageCollection; }
        }

        #endregion

        #region IOutboxMessageCollection Members

        public void Refresh()
        {
            _messages = null;
            _manager.Renew();
        }

        public int Count
        {
            get
            {
                CheckLoad();
                return _messages.Count;
            }
        }

        public IEnumerator<IOutboxMessage> GetEnumerator()
        {
            CheckLoad();
            return _messages.Cast<IOutboxMessage>().GetEnumerator();
        }

        [NotNull]
        IEnumerator IEnumerable.GetEnumerator()
        {
            CheckLoad();
            return _messages.GetEnumerator();
        }

        #endregion

        #region ITreeNode Members

        bool ITreeNode.HasChildren
        {
            get
            {
                CheckLoad();
                return _messages.Count > 0;
            }
        }

        ITreeNode ITreeNode.this[int index]
        {
            get
            {
                CheckLoad();
                return _messages[index];
            }
        }

        NodeFlags ITreeNode.Flags { get; set; }

        ITreeNode ITreeNode.Parent
        {
            get { return _manager; }
        }

        bool ICollection.IsSynchronized
        {
            get { return false; }
        }

        void ICollection.CopyTo(Array array, int index)
        {
            throw new NotSupportedException();
        }

        [NotNull]
        object ICollection.SyncRoot
        {
            get { return this; }
        }

        #endregion

        public void Delete(NewMessage msg)
        {
            using (IJanusDataContext db = _provider.CreateDBContext())
            {
                db.OutboxMessages(m => m.ID == msg.ID).Delete();
            }

            Refresh();
        }

        public void Add(MessageInfo msgInfo)
        {
            OutboxHelper.AddOutboxMessage(_provider, msgInfo);
            Refresh();

            int maxId = int.MinValue;
            foreach (IOutboxMessage newMessage in this)
            {
                if (newMessage.ID > maxId)
                {
                    maxId = newMessage.ID;
                }
            }
        }

        private void CheckLoad()
        {
            if (_messages == null)
            {
                lock (_loadFlag)
                {
                    if (_messages == null)
                    {
                        Load();
                    }
                }
            }
        }

        private void Load()
        {
            using (IJanusDataContext db = _provider.CreateDBContext())
            {
                IQueryable<DataModel.IOutboxMessage> outboxMessages1 = 
                    db.OutboxMessages(m => m.Hold == _draftMessage);

                IOrderedQueryable<DataModel.IOutboxMessage> outboxMessages2 =
                    outboxMessages1.OrderByDescending(m => m.ID);

                _messages =
                    outboxMessages2
                        .Select(
                            m =>
                            new NewMessage(
                                m.ID, 
                                m.ForumID, 
                                m.ServerForum.Name, 
                                m.Subject, 
                                m.ReplyToID, 
                                m.Hold, 
                                this))
                        .ToList();
            }
        }
    }
}